
package com.zhihuishu.treenity.service.course.impl;


import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.objectweb.asm.Handle;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import com.able.commons.dto.BaseVideoDto;
import com.able.commons.httpinvoker.IFileCommonsInvoker;
import com.able.openapi.overseas.IOnlineSchoolForOverseasService;
import com.able.openapi.overseas.dto.RecruitTreenityDto;
import com.alibaba.dubbo.common.utils.Assert;
import com.zhihuishu.micro.course.openapi.course.CourseOpenService;
import com.zhihuishu.micro.course.openapi.course.dto.CourseClipsOpenDto;
import com.zhihuishu.micro.course.openapi.course.dto.CourseOpenDto;
import com.zhihuishu.remote.RemoteException;
import com.zhihuishu.remote.RemoteResult;
import com.zhihuishu.toolkit.jedis.BeanWrapper;
import com.zhihuishu.toolkit.jedis.JedisHelper.Handler;
import com.zhihuishu.toolkit.jedis.JedisHelper.ReturnHandler;
import com.zhihuishu.toolkit.jedis.template.JedisExecutor;
import com.zhihuishu.toolkit.jedis.template.JedisTemplate;
import com.zhihuishu.treenity.consts.Constants;
import com.zhihuishu.treenity.helper.RedisKeyHelper;
import com.zhihuishu.treenity.service.course.CcCourseService;
import com.zhihuishu.treenity.service.course.CourseService;
import com.zhihuishu.treenity.service.impl.BaseService;

import net.sf.json.JSONObject;
import redis.clients.jedis.Jedis;

@Service("courseService")
public class CourseServiceImpl extends BaseService implements CourseService {
 
	@Resource
	private CourseOpenService courseOpenService ;
	
	@Autowired
	private IFileCommonsInvoker IFileCommonsInvoker;
	
	@Autowired
	private CcCourseService treenityCcCourseOpenService; 
	
	@Autowired
	private IOnlineSchoolForOverseasService treenityIOnlineSchoolForOverseasService;
	
	@Autowired
	private JedisTemplate jedisTemplate;
	
	@Autowired
	private JedisExecutor jedisExecutor;
	
	private JSONObject jSONObject= new JSONObject();
	
	@Override
	public RemoteResult<CourseOpenDto> queryCourseInfo(long courseId) throws RemoteException {
		RemoteResult<CourseOpenDto> result=new RemoteResult<CourseOpenDto> ();
		
		if(courseId >0){
			try {
				result = courseOpenService.queryCourseInfo(courseId);
				if(result.isSuccess()){
					result.setSuccess(true);
					return result;
				}
			} catch (Exception e) {
				
				result.setExceptionStack(e);
			}
		}else{
			result.setExceptionStack(new Exception("课程id有误 ！"));
		}
		result.setSuccess(false);
		result.setResult(null);
		
		return result;
	}
	
	@Override
	public RemoteResult<Void> updateCourseInfo(CourseOpenDto course, long updateUser) throws RemoteException {
		
		RemoteResult<Void> result=new RemoteResult<Void>();
		
		if(course !=null && updateUser >0){
			
			try {
				result = courseOpenService.update(course, updateUser);
				if(result.isSuccess()){
					result.setSuccess(true);
					return result;
				}
			} catch (Exception e) {
				result.setExceptionStack(e);
				return result;
			}
		}else{
			result.setExceptionStack(new Exception("课程信息有误！"));
		}
		result.setSuccess(false);
		result.setResult(null);
		
		return result;
	}

	@SuppressWarnings("unused")
	@Override
	public void remove(long courseId, long deleteUser) throws RemoteException {
		RemoteResult<Void> result= courseOpenService.remove(courseId, deleteUser);
		treenityCcCourseOpenService.delProgressByCourseId(courseId);
		
	}

	@Override
	public CourseOpenDto create(String courseName, long createUser) throws RemoteException {
		RemoteResult<CourseOpenDto> result = courseOpenService.create(courseName, createUser);
		if(result.isSuccess()){
			return result.getResult();
		}
		return null;
		
	}

	@Override
	public  RemoteResult<Void> updateCourseName(CourseOpenDto courseOpenDto, long courseId) throws RemoteException {
		RemoteResult<Void> result=courseOpenService.update(courseOpenDto, courseId);
		if(result.isSuccess()){
			return result;
		}
		return null;
	}



	@Override
	public RemoteResult<CourseClipsOpenDto> queryClipseOpenDto(long clipsId) throws RemoteException {
		RemoteResult<CourseClipsOpenDto> result=new RemoteResult<CourseClipsOpenDto>();
		
		if(clipsId >0){
			try {
				 result = courseOpenService.queryCourseClips(clipsId);
				if(result.isSuccess()){
					result.setSuccess(true);
					return result;
				}
			} catch (Exception e) {
				result.setExceptionStack(e);
			}
		}else{
			result.setExceptionStack(new Exception("片花id有误 ！"));
		}
		result.setResult(null);
		result.setSuccess(false);
		
		return result;
	}
	
	

	@Override
	public RemoteResult<Void> UpdateClipseCourese(CourseClipsOpenDto clipsOpen) throws RemoteException {
		RemoteResult<Void> result =new RemoteResult<Void>();
		
		if(clipsOpen.getClipsId()>0 && clipsOpen.getVideoId()>0){
			
			try {
				result = courseOpenService.updateCourseClips(clipsOpen);
				if(result.isSuccess()){
					result.setSuccess(true);
					return result;
				}
			} catch (Exception e) {
				result.setExceptionStack(e);				
			}	
		}else{
			result.setExceptionStack(new Exception("片花id、视频id有误 ！"));
		}
		result.setSuccess(false);
		result.setResult(null);
		
		return result;
	}
	
	
	@Override
	public RemoteResult<Long> saveClips(CourseClipsOpenDto clipsOpen, long courseId,long updateUser) throws RemoteException {
		RemoteResult<Long> result = new RemoteResult<Long>();
		
		if(courseId >0 && clipsOpen !=null){
			try {
				result = courseOpenService.createCourseClips(courseId, clipsOpen);
				if(result.isSuccess()){
					result.setSuccess(true);
					return result;
				}
			} catch (Exception e) {
				result.setExceptionStack(e);
			}
		}else{
			result.setExceptionStack(new Exception("片花信息有误！"));
		}
		result.setResult(null);
		result.setSuccess(false);
		
		return result;
	}
	
	public RemoteResult<CourseOpenDto> loadCourse(long courseId) throws RemoteException {
		return this.queryCourseInfo(courseId);
	}
	
	
	
	

	/**
	 * 根据VideoId更新片花封面
	 * @param clipsId
	 * @return
	 * @throws RemoteException
	 */
	@Override
	public RemoteResult<CourseClipsOpenDto> updatePromoVideoImg(CourseClipsOpenDto clipsOpen, long courseId,long updateUser) throws RemoteException {
		RemoteResult<CourseClipsOpenDto> result =new RemoteResult<CourseClipsOpenDto>();
		
		if(clipsOpen.getVideoId() >0 && clipsOpen.getClipsId() >0){
			try {
				List<BaseVideoDto> list = IFileCommonsInvoker.findVideoByIds(clipsOpen.getVideoId().toString());
				String img=list.get(0).getThumbnailPath();
				String videoPath=list.get(0).getStorage();
				//如果视频封面不存在或者为默认图片，则不做操作。
				if(img.equalsIgnoreCase(Constants.COURSE_PROMOVIDEO_IMG_PATH)){
					result.setSuccess(true);
					clipsOpen.setVideoImage("");
					result.setResult(clipsOpen);
					return result;
				}
				clipsOpen.setVideoPath(videoPath);
				clipsOpen.setVideoImage(img);
				//转码成功，更新片花封面
				RemoteResult<Void> openResult =courseOpenService.updateCourseClips(clipsOpen);
				if(openResult.isSuccess()){
					result.setSuccess(true);
					result.setResult(clipsOpen);
					return result;
				}
			} catch (Exception e) {				
				result.setExceptionStack(e);				
			}
		}else{
			result.setExceptionStack(new Exception("片花id 、视频id 有误 ！"));
		}
		result.setSuccess(false);
		result.setResult(null);
		
		return result;
	}
	
	@Override
	public RemoteResult<CourseOpenDto> releaseCourse(CourseOpenDto course, long updateUser) throws RemoteException {
		//Category 1必修 2选修  默认1
/*		if(course.getCourseCategory()==null){
			course.setCourseCategory(1);
		}*/
		RemoteResult<CourseOpenDto> newResult = new RemoteResult<CourseOpenDto>();
		RemoteResult<Void> result = courseOpenService.update(course, updateUser);
		if(result.isSuccess()){
			newResult.setResult(course);
		}
		
		return newResult;
	}
	
	@Override
	//从接口取数据，并封装排序
	public List<RecruitTreenityDto> findCourseListByUserId(long userId) throws RemoteException {
		//从学堂接口获取当前用户有权限的所有课程
		List<Long> AssistantsCourseIds = treenityIOnlineSchoolForOverseasService.findAssistantsCourseByUserId(userId);
		//返回之前所获取到的课程id list 中的海外课程对象list
		//这里只所以要获取对象而不是获取ID  是因为接下来的程序还要用到，无需再次调用接口
		RemoteResult<List<CourseOpenDto>> result = courseOpenService.overseasCourseList(AssistantsCourseIds);
		List<CourseOpenDto> treenityCourseIds = new ArrayList<CourseOpenDto>();
		if(result.isSuccess()){
			treenityCourseIds = result.getResult();
		}
		//将两个集合 取交集 获得当前用户下的所有海外课程ID list
		List<Long> courseIds = intersectionCourseIds(AssistantsCourseIds,treenityCourseIds);
		List<RecruitTreenityDto> recruitList =null;
		//调用学堂接口 返回有招生的集合
		recruitList = treenityIOnlineSchoolForOverseasService.getRecruitList(courseIds);
		if(null != recruitList && recruitList.size()>0){
			for (RecruitTreenityDto recruitTreenityDto : recruitList) {
				if(courseIds.contains(recruitTreenityDto.getCourseId())){
					courseIds.remove(recruitTreenityDto.getCourseId());
				}
			}
		}
		//将没有招生的课程也封装
		recruitList = findNoRecruitCourse(recruitList,courseIds,treenityCourseIds);
		//排序
		//this.sort(recruitList);
		return recruitList;
	}
	
	//排序规则
	private void sort(List<RecruitTreenityDto> recruitList){
		Collections.sort(recruitList, new Comparator<RecruitTreenityDto>() {

			@Override
			public int compare(RecruitTreenityDto r1, RecruitTreenityDto r2) {
				int num1 = r1.getType()-r2.getType();
				int num2 = (num1==0 ? r2.getRecruitId()-r1.getRecruitId() : num1);
				int num3 = (int) (num2==0?r2.getCourseId()-r1.getCourseId():num2);
				return num3;
			}
		});
	}

	//封装数据，没招生数据的课程
	private List<RecruitTreenityDto> findNoRecruitCourse(List<RecruitTreenityDto> recruitList, List<Long> courseIds,
			List<CourseOpenDto> treenityCourseIds) {
		if(null == courseIds || courseIds.size()==0){
			return recruitList;
		}
		if(null == treenityCourseIds || treenityCourseIds.size()==0){
			return recruitList;
		}
		
		for (Long courseId : courseIds) {
			for (CourseOpenDto CourseOpenDto : treenityCourseIds) {
				if(CourseOpenDto.getCourseId().equals(courseId)){
					RecruitTreenityDto recruitDto = new RecruitTreenityDto();
					recruitDto.setCourseId(courseId);
					recruitDto.setCourseName(CourseOpenDto.getName());
					recruitDto.setRecruitId(-1);
					recruitDto.setType(0);
					recruitList.add(recruitDto);
				}
			}
		}
		return recruitList;
	}

	//取海外项目的课程和有权限修改的课程交集
	private List<Long> intersectionCourseIds(List<Long> assistantsCourseIds, List<CourseOpenDto> treenityCourseIds) {
		if(null == treenityCourseIds || treenityCourseIds.size()==0){
			return null;
		}
		if(null == assistantsCourseIds || assistantsCourseIds.size()==0){
			return null;
		}
		List<Long> courseIds = new ArrayList<Long>();
		for (CourseOpenDto courseOpenDto : treenityCourseIds) {
			if(assistantsCourseIds.contains(courseOpenDto.getCourseId())){
				courseIds.add(courseOpenDto.getCourseId());
			}
		}
		
		return courseIds;
		
	}

	@Override
	public List<Long> findUserMaintainableCourseIds(long userId) throws RemoteException {
		List<Long> AssistantsCourseIds = treenityIOnlineSchoolForOverseasService.findUserMaintainableCourseIds(userId);
		RemoteResult<List<CourseOpenDto>> result = courseOpenService.overseasCourseList(AssistantsCourseIds);
		List<CourseOpenDto> treenityCourseIds = new ArrayList<CourseOpenDto>();
		if(result.isSuccess()){
			treenityCourseIds = result.getResult();
		}
		List<Long> courseIds = intersectionCourseIds(AssistantsCourseIds,treenityCourseIds);
		return courseIds;
	}

	@Override
	public RecruitTreenityDto getRecruitBycourseId(Long courseId) {
		RecruitTreenityDto treenityDto = treenityIOnlineSchoolForOverseasService.getRecruitBycourseId(courseId);
		return null==treenityDto ? null : treenityDto;
	}

	//从缓存拿数据，如果缓存不存在，就走接口取，并将获取到的值存入缓存
	@Override
	public List<RecruitTreenityDto> getCourseList(Long userId) throws RemoteException {
		Assert.notNull(userId, "userId must not be null");
		
		List<RecruitTreenityDto> recruitList = this.getRedisCourseList(userId);
		if(CollectionUtils.isEmpty(recruitList)){
			recruitList = this.setRedisCourseList(userId);
		}
		if(!CollectionUtils.isEmpty(recruitList)){
			this.sort(recruitList);
		}
		return recruitList;
	}

	//走接口取数据，并将取到的值存入缓存
	private List<RecruitTreenityDto> setRedisCourseList(final Long userId) throws RemoteException {
		final List<RecruitTreenityDto> recruitList = this.findCourseListByUserId(userId);
		if(!CollectionUtils.isEmpty(recruitList)){
			jedisExecutor.execute(new Handler() {
				@Override
				public void handle(Jedis jedis) {
					for (RecruitTreenityDto recruitTreenityDto : recruitList) {
						//jedis.rpush(RedisKeyHelper.getCourseListKey(userId), jSONObject.fromObject(recruitTreenityDto).toString());
						jedis.sadd(RedisKeyHelper.getCourseListKey(userId), jSONObject.fromObject(recruitTreenityDto).toString());
					}
					jedis.expire(RedisKeyHelper.getCourseListKey(userId), Constants.REDIS_TIME);
				}
			});
		}
		return recruitList;
	}

	//从缓存中取值
	private List<RecruitTreenityDto> getRedisCourseList(Long userId) {
		final String key = RedisKeyHelper.getCourseListKey(userId);
		
		/*BeanWrapper<List<String>> executeAndReturn = jedisExecutor.executeAndReturn(new ReturnHandler<List<String>>() {
			@Override
			public List<String> handle(Jedis jedis) {
				List<String> list = null;
				if(StringUtils.isNotBlank(key)){
					list = jedis.lrange(key, 0, -1);
				}
				return list;
			}
		});*/
		BeanWrapper<Set<String>> executeAndReturn = jedisExecutor.executeAndReturn(new ReturnHandler<Set<String>>() {

			@Override
			public Set<String> handle(Jedis jedis) {
				Set<String> list = null;
				if(StringUtils.isNotBlank(key)){
					list = jedis.smembers(key);
				}
				return list;
			}
		});

		Set<String> list = executeAndReturn.getValue();
		if(CollectionUtils.isEmpty(list)) return null;
		List<RecruitTreenityDto> recruitList = new ArrayList<RecruitTreenityDto>();
		for (String jsonStr : list) {
	        JSONObject obj = jSONObject.fromObject(jsonStr);
	        RecruitTreenityDto recruit = (RecruitTreenityDto) jSONObject.toBean(obj, RecruitTreenityDto.class);
	        recruitList.add(recruit);
		}
		return recruitList;
	}

	@Override
	public void delRedisCourseList(Long curUserId) {
		Assert.notNull(curUserId, "userId must not be null");
		String key = RedisKeyHelper.getCourseListKey(curUserId);
		jedisTemplate.del(key);
	}

}
